﻿using System;
using System.Collections.Generic;
using System.Text;
using Krile.Kernel;
using Krile.Kernel.Plugin.Operations.AgentElements;
using Krile.Common;

namespace Wassrile.Operation
{
    public class StatusControl : IStatusControl,IDisposable
    {
        public StatusControl()
        {
            Receiver = new Wassrile.Operation.Web.StatusReceiver();
        }

        public Web.StatusReceiver Receiver = null;

        public bool Destroiable
        {
            get { return false; }
        }

        public OperationResult<object> Destroy(ulong uid)
        {
            throw new NotImplementedException();
        }

        public void ReceiveStatuses()
        {
            Receiver.DoReceive();
        }

        public bool RecvGlobalTimeline
        {
            get { return Core.Config.State.ImplyGlobalTL; }
            set { Core.Config.State.ImplyGlobalTL = value; }
        }

        //*CONST::お気に入り追加URI(+id.json)
        const string AddFavorURI = "http://api.wassr.jp/favorites/create/";
        //*CONST::お気に入り削除URI(+id.json)
        const string DeleteFavorURI = "http://api.wassr.jp/favorites/destroy/";
        //*CONST::チャンネルお気に入りURI(+id)
        const string ToggleChannelFavURI = "http://api.wassr.jp/channel_favorite/toggle.json?channel_message_rid=";

        public OperationResult<object> SetFavorite(ulong uid, bool create)
        {
            if (!Bridge.StatusManager.IdExists(uid))
                throw new ArgumentException("Status uid:" + uid.ToString() + " isn't exists in Krile.");
            var ws = (DataClasses.WStatus)Bridge.StatusManager.GetStatus(uid);
            if (ws.channelId != null)
            {
                //channel
                return Web.Connect.WebOperation(
                    new Uri(ToggleChannelFavURI + ws.Id),
                    "POST");
            }
            else
            {
                //timeline
                if (create)
                {
                    //channel
                    return Web.Connect.WebOperation(
                        new Uri(AddFavorURI + ws.Id + ".json"),
                        "POST");
                }
                else
                {
                    //channel
                    return Web.Connect.WebOperation(
                        new Uri(DeleteFavorURI + ws.Id + ".json"),
                        "POST");
                }
            }
        }

        public bool Updatable
        {
            get { return true; }
        }

        //*CONST::ステータス投稿URI
        const string UpdateStatusURI = "http://api.wassr.jp/statuses/update.json";
        const string UpdateChannelStatusURI = "http://api.wassr.jp/channel_message/update.json?name_en=";
        //*CONST::投稿リミット
        const int PostDataLimit = 255;
        public OperationResult<object> Update(string text, ulong replyto, object affixObject)
        {
            if (text.Length > PostDataLimit) text = text.Substring(0, PostDataLimit);
            Uri target = null;
            bool postCh = false;
            bool postImg = false;

            var xd = affixObject as Controls.WInput.WExtraData;
            if (xd != null)
            {
                postCh = xd.ChannelId != null;
                postImg = xd.LinkPicturePath != null;
            }

            if (text.StartsWith("#"))
            {
                int ed = text.IndexOf(' ');
                string ch = text.Substring(1, ed);
                text = text.Substring(ed + 1);
                if (xd == null)
                    xd = new Wassrile.Controls.WInput.WExtraData(null, ch);
                else
                    xd.ChannelId = ch;
                postCh = true;
            }

            if (postCh)
                target = new Uri(UpdateChannelStatusURI + xd.ChannelId);
            else
                target = new Uri(UpdateStatusURI);

            if (Core.Config.Post.useSignature)
                text += Core.Config.Post.Signature;

            OperationResult<object> ret = null; 
            if (postImg)
            {
                string boundary = Guid.NewGuid().ToString("N");
                string separator = "--" + boundary + "\r\n";

                //WebPostBinを使うので、SendDataのパラメータ名に=は不要
                var sdList = new List<NetConnect.SendData>();
                if (postCh)
                {
                    sdList.Add(new NetConnect.SendData("body", text));
                    if (replyto != 0 && Bridge.StatusManager.IdExists(replyto))
                        sdList.Add(new NetConnect.SendData("reply_channel_message_rid", Bridge.StatusManager.GetStatus(replyto).Id));
                }
                else
                {
                    sdList.Add(new NetConnect.SendData("source", Bridge.Config.AppName));

                    sdList.Add(new NetConnect.SendData("status", text));
                    if (replyto != 0 && Bridge.StatusManager.IdExists(replyto))
                        sdList.Add(new NetConnect.SendData("reply_status_rid", Bridge.StatusManager.GetStatus(replyto).Id));
                }
                sdList.Add(new NetConnect.SendData("image", xd.LinkPicturePath, true));
                ret = Web.Connect.WebPostBin(target, sdList.ToArray());
            }
            else
            {
                StringBuilder data = new StringBuilder(100);
                if (postCh)
                {
                    data.Append("body=" + Uri.EscapeDataString(text));
                    if (replyto != 0 && Bridge.StatusManager.IdExists(replyto))
                        data.Append("&reply_channel_message_rid=" + Bridge.StatusManager.GetStatus(replyto).Id);
                }
                else
                {
                    data.Append("source=" + Uri.EscapeDataString(Bridge.Config.AppName));
                    data.Append("&status=" + Uri.EscapeDataString(text));
                    if (replyto != 0 && Bridge.StatusManager.IdExists(replyto))
                        data.Append("&reply_status_rid=" + Bridge.StatusManager.GetStatus(replyto).Id);
                }
                byte[] pd = Encoding.ASCII.GetBytes(data.ToString());
                ret = Web.Connect.WebPost(target, pd);
            }
            if (Core.Config.Post.refreshAfterPost)
            {
                //Async recv
                Action act = new Action(ReceiveStatuses);
                act.BeginInvoke((iar) => ((Action)iar.AsyncState).EndInvoke(iar), act);
                //ReceiveStatuses();
            }
            return ret;
        }
        
        public void Dispose()
        {
            Receiver.Dispose();
        }

        public ulong GetUidFromServiceStatusId(string id)
        {
            return Web.DataMan.GetUIDFromWID(id);
        }

        public bool ServiceStatusIdExists(string id)
        {
            return Web.DataMan.WidExists(id);
        }

        public bool AutoCreateFavOperationTriggers
        {
            get { return true; }
        }

        public bool AutoCreateReplyOperationTriggers
        {
            get { return true; }
        }

        public bool AutoCreateDeleteOperationTriggers
        {
            get { return false; }
        }
    }
}
